﻿/** 
 *  @file
 *  @brief   可扩展的单元工厂
 *  @author  wanghuan
 *  @date    2023.11.05
 *  @version v1.0
 *  @par Copyright(c):  ShenGong  Simulation corporation
 */
#pragma once
#include <vector>
#include <memory>

#include "DataStructure/Common/Real.h"
#include "DataStructure/Input/Element/ElementTypes.h"
#include "DBManager/DBServiceFactory.h"
#include "SGFem/ElementCalculator/Common/ElementCalculatorExport.h"

SG_FEMSOLVER_ELEMENT_NAMESPACE_OPEN
/// @brief 单元计算接口类
class IElementCalculator
{
public:
    virtual ~IElementCalculator () = default;

    /** @brief 初始化
     * 
     * 一些单元只是在积分格式或者是否选择减缩积分方面不同，因此可共用一个单元计算派生类
     * 通过注入type，本函数类实现具体单元计算类的个性化构造（builder，提供实现的灵活性）。避免两个差异很小的单元中出现重复代码
     * 
     * 本函数实际上会计算一些同种单元的公共数据（如与单元节点坐标和属性等单元个性数据无关的量。 典型如积分点数据已经积分点形函数及其对参数坐标导数）
     */
    virtual void Initialize (SG::DataStructure::FEM::ElementTypes type) = 0;

    /** @brief 计算和位移无关的单元矩阵 （刚度 质量矩阵和 体积力）
     *
     * @param dbServiceFactory 有限元模型数据；const限定符表示针本身是常量，指针指向的内容可以修改。 一些计算结果数据可能需要被保持到数据库中
     */
    virtual void ComputeElementMatries (const SG::DBManager::DBServiceFactorySP dbServiceFactory) = 0;

    /** @brief 计算单元应力，应变，内力等派生结果数据
     * 
     * @param dbServiceFactory   网格数据
     * @param subcaseId          当前工况号，传入工况时为了进行数据保存。
     * @param time               静力分析传入 0.0， 模态分析传入模态阶数， 瞬态分析传入当前 时间参数
     * @param globalDisplacement 当前工况计算的结构整体位移向量
     */
    virtual void DataRecovery (const SG::DBManager::DBServiceFactorySP dbServiceFactory, int subcaseId, SG::DataStructure::Common::Real time, const std::vector<SG::DataStructure::Common::Real>& globalDisplacement) = 0;
    
    /** @brief 线性屈曲分析计算单元的应力刚度
     * 
     * @param dbServiceFactory   网格数据
     * @param staticSubId        静力工况号，用于查询计算应力刚度需要的数据
     */      
    virtual void ComputeStressStiffness (const SG::DBManager::DBServiceFactorySP dbServiceFactory, int staticSubId) = 0;
};

/// @brief 声明共享指针
using ElementCalculatorSP = std::shared_ptr<IElementCalculator>;

SG_FEMSOLVER_ELEMENT_NAMESPACE_CLOSE